<!DOCTYPE HTML>
<html lang="zh-CN">

<head><meta name="generator" content="Hexo 3.9.0">
    <!-- hexo-inject:begin --><!-- hexo-inject:end --><!--Setting-->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta http-equiv="Cache-Control" content="no-siteapp">
    <meta http-equiv="Cache-Control" content="no-transform">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta name="apple-mobile-web-app-capable" content="AncyBlog">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="format-detection" content="telephone=no,email=no,adress=no">
    <meta name="browsermode" content="application">
    <meta name="screen-orientation" content="portrait">
    <meta name="theme-version" content="1.2.3">
    <meta name="root" content="/">
    <link rel="dns-prefetch" href="http://www.anciety.de">

    <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
    </script>
    <!--SEO-->

<meta name="keywords" content="CTF,codegate,writeups,reverse">


<meta name="description" content="CodeGate 两道简单题 (2)
reverse: RS
题目信息
题目给了一个文件 result 和一个 binary ，先看看 result 里边的内容：
12$ ./rsef 43 4...">


<meta name="robots" content="all">
<meta name="google" content="all">
<meta name="googlebot" content="all">
<meta name="verify" content="all">
    <!--Title-->

<title>
    
    codegate-2020-2 |
    
    AncyBlog
</title>

<link rel="alternate" href="/atom.xml" title="AncyBlog" type="application/atom+xml">


<link rel="icon" href="/favicon.png">

    

<link rel="stylesheet" href="/css/bootstrap.min.css?rev=3.3.7">
<link rel="stylesheet" href="/css/font-awesome.min.css?rev=4.7.0">
<link rel="stylesheet" href="/css/style.css?rev=@@hash">
    



<script type="text/javascript" src="https://tajs.qq.com/stats?sId=66471611" charset="UTF-8"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->


    

</head>
</html>
<!--[if lte IE 8]>
<style>
    html{ font-size: 1em }
</style>
<![endif]-->
<!--[if lte IE 9]>
<div style="ie">你使用的浏览器版本过低，为了你更好的阅读体验，请更新浏览器的版本或者使用其他现代浏览器，比如Chrome、Firefox、Safari等。</div>
<![endif]-->
<body>
    <!-- hexo-inject:begin --><!-- hexo-inject:end --><header class="main-header"  style="background-image:url(
    https://www.anciety.de/img/banner.jpg)"
     >
    <div class="main-header-box">
        <a class="header-avatar" href="/" title='Anciety'>
            <img src="/img/avatar.jpg" alt="logo头像" class="img-responsive center-block">
        </a>
        <div class="branding">
            <!--<h2 class="text-hide">Snippet主题,从未如此简单有趣</h2>-->
            
            <h2>
                Hacked By Swing
            </h2>
            
        </div>
    </div>
</header>
    <nav class="main-navigation">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="navbar-header"><span class="nav-toggle-button collapsed pull-right" data-toggle="collapse" data-target="#main-menu" id="mnav">
                        <span class="sr-only"></span>
                        <i class="fa fa-bars"></i>
                    </span>
                    <a class="navbar-brand" href="http://www.anciety.de">
                        AncyBlog</a>
                </div>
                <div class="collapse navbar-collapse" id="main-menu">
                    <ul class="menu">
                        
                        <li role="presentation" class="text-center">
                            <a href="/"><i class="fa "></i>
                                首页</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/writeups/"><i class="fa "></i>
                                writeups</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/学习/"><i class="fa "></i>
                                学习</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/问题解决/"><i class="fa "></i>
                                问题解决</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/categories/扯淡/"><i class="fa "></i>
                                扯淡</a>
                        </li>
                        
                        <li role="presentation" class="text-center">
                            <a href="/archives/"><i class="fa "></i>
                                时间轴</a>
                        </li>
                        
                    </ul>
                </div>
            </div>
        </div>
    </div>
</nav>
    <section class="content-wrap">
        <div class="container">
            <div class="row">
                <main class="col-md-8 main-content m-post">
                    <p id="process"></p>
<article class="post">
    <div class="post-head">
        <h1 id="codegate-2020-2">
            
            codegate-2020-2
            
        </h1>
        <div class="post-meta">
    
    <span class="categories-meta fa-wrap">
        <i class="fa fa-folder-open-o"></i>
        <a class="category-link" href="/categories/writeups/">writeups</a>
    </span>
    
    
    <span class="fa-wrap">
        <i class="fa fa-tags"></i>
        <span class="tags-meta">
            
            <a class="tag-link" href="/tags/CTF/">CTF</a> <a class="tag-link" href="/tags/codegate/">codegate</a> <a class="tag-link" href="/tags/reverse/">reverse</a> <a class="tag-link" href="/tags/writeups/">writeups</a>
            
        </span>
    </span>
    
    
    
    <span class="fa-wrap">
        <i class="fa fa-clock-o"></i>
        <span class="date-meta">
            2020/02/09</span>
    </span>
    
    <span class="fa-wrap">
        <i class="fa fa-eye"></i>
        <span id="busuanzi_value_page_pv"></span>
    </span>
    
    
</div>
        
        
    </div>
    
    <div class="post-body post-content">
        <h1 id="codegate-两道简单题-2">CodeGate 两道简单题 (2)</h1>
<h2 id="reverse-rs">reverse: RS</h2>
<h3 id="题目信息">题目信息</h3>
<p>题目给了一个文件 <code>result</code> 和一个 binary ，先看看 result 里边的内容：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ ./rs</span><br><span class="line">ef 43 4b 3f 5e b9 f0 d0 8c b5 7e 6f 7b c8 a6 7b 09 e2 61 9d 98 03 5f 56 5d 66 82 0b 9e 2b 76 92 5b c3 dc f2 3c d0 b6 81 60 34 a5 66 ca bd 7d 6a 00 fe e4 0b 44 e1 ba 81 cb ae 8b 24 0b a5 1f 6d ba 0e 61 1a 30 a7 77 51 23 41 a6 1a c0 7f 71 71 9f d5 93 e5 38 ce 52 8b 25 86 b3 12 b7 a7 1c 43 b4 08 81 47 ae d6 18 46 c5 6b 69 63 0b cc 95 ab 49 53 6f de be 2f 2e d9 9b dc dd 76 69 a4 f0 58</span><br></pre></td></tr></table></figure>
<p>这个意思很明确了，那么我们也运行一下这个 binary 试试：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ ./rs</span><br><span class="line">thread <span class="string">'main'</span> panicked at <span class="string">'Cannot open flag: Os &#123; code: 2, kind: NotFound, message: "No such file or directory" &#125;'</span>, src/libcore/result.rs:999:5</span><br><span class="line">note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.</span><br></pre></td></tr></table></figure>
<p>这个意思熟悉 Rust 的同学应该可以一下意识到，不熟悉的看这个报错也差不多可以猜到，是缺少文件，所以我直接在本地建了一个名为 flag 的文件（如果不对还可以尝试 <code>/flag</code>, <code>/home/ctf/flag</code> 等路径），内容的话就写了 <code>flag</code> 然后看看输出结果：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ ./rs</span><br><span class="line">79 22 e2 6a 67 ec 4d 77 c1 95 cf <span class="built_in">cd</span> ef d8 3d bd f1 28 5a 44 41 07 a8 64 91 4b 8a ed b9 fa d0 e6</span><br></pre></td></tr></table></figure>
<p>那么看起来就是 flag 里的内容被加密了，这是加密的输出内容，然后加密的内容在当前目录的 flag 文件里。</p>
<p>这个时候我打算心存侥幸的尝试一下看看输出内容有没有一些规律，所以我又加密了 <code>flagflagflagflag</code> 的内容：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ ./rs</span><br><span class="line">40 c7 02 78 81 46 a7 a2 7c cf d8 83 87 9e 39 b8 de 49 15 8d 97 2b 1c f6 16 bf 53 f0 52 b6 42 ba c0 17 f4 6b f5 fb ea 79 c3 ee bc c8 4e 14 8d 87 35 d4 db 14 56 e8 2f 71 b1 a4 05 74 34 34 13 6f</span><br></pre></td></tr></table></figure>
<p>可以看到出现了重复，这个时候心里基本有了点数了，接下来再尝试看看更改一个值会出现什么内容：</p>
<p>加密 <code>flagflagflagflagf</code></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ ./rs</span><br><span class="line">40 c7 02 78 81 46 a7 a2 7c cf d8 83 87 9e 39 b8 de 49 15 8d 97 2b 1c f6 16 bf 53 f0 52 b6 42 ba 3b cb f5 b6 15 8a e4 87 76 60 86 02 1d 5c 8b b5 fd a9 59 65 d4 f8 e8 05 09 2b 22 a1 89 8c f5 36</span><br></pre></td></tr></table></figure>
<p>可以看到前半部分是没有发生变化的，但是最后发生变化了，说明整个加密过程是分块的，而且分块的结果没有办法直接通过不逆向进行猜测，统计规律丢失还是比较严重的（有点类似 hash ，更改了一个字母会导致这个块都发生变化，而不是只引起几个字母发生变化，这样的话就没办法通过不逆向直接获取了）。</p>
<p>所以接下来就要去进行逆向部分。</p>
<h3 id="找到关键函数">找到关键函数</h3>
<p>程序是用 Rust 写的，并且已经被 strip 了，整个程序看起来很大，而且有许多是 Rust 的库函数，我们也没有太好的办法可以直接看出来是不是 Rust 的库函数，所以一个一个逆是肯定不可能的。</p>
<p>所以任务的第一步是找到输入位置和输出位置，从而找到真正进行加密的位置。</p>
<p>输入位置的获取通过在 read 函数下断点，可以得到输入的目标，也就是存储了 flag 中的明文数据的位置，需要注意的是，在逆向的时候一定要把 ASLR 关掉，如果在 linux 下，使用 gdb 如果有权限应该是会自动关掉的，否则后面下 watchpoint 就不好办了：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">(gdb) b read</span><br><span class="line">(gdb) c</span><br><span class="line"></span><br><span class="line"> RAX  0xe</span><br><span class="line"> RBX  0x7fffffffddc0 ◂— 0x0</span><br><span class="line"> RCX  0xe</span><br><span class="line"> RDX  0xe</span><br><span class="line"> RDI  0x3</span><br><span class="line"> RSI  0x55555579db72 ◂— 0x0</span><br><span class="line"> R8   0x55555579db60 ◂— &apos;flagflagflagflagf\n&apos;</span><br><span class="line"> R9   0x1</span><br><span class="line"> R10  0x30</span><br><span class="line"> R11  0x246</span><br><span class="line"> R12  0x7fffff7ff000 ◂— 0x0</span><br><span class="line"> R13  0x7fffff7fe000</span><br><span class="line"> R14  0x7fffffffe140 ◂— 0x0</span><br><span class="line"> R15  0x7ffff7f64b20 (sigaction) ◂— endbr64</span><br><span class="line"> RBP  0x0</span><br><span class="line"> RSP  0x7fffffffdcd8 —▸ 0x55555556a363 ◂— cmp    rax, -1</span><br><span class="line"> RIP  0x7ffff7f63640 (read) ◂— endbr64</span><br></pre></td></tr></table></figure>
<p>这个过程 c 了两次其实，然后就看到了字符串，接下来我需要找到什么地方使用了这个字符串，所以：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(gdb) rw *0x55555579db60</span><br><span class="line">(gdb) c</span><br></pre></td></tr></table></figure>
<p>接下来的逆向过程就比较枯燥了，通过查看每一个使用到的地方，去使用到的地方附近找，看有没有出现可疑的程序模式：</p>
<ol type="1">
<li>循环：因为程序是类似块加密的，既然有分块，就一定存在循环，而且程序存在改一个字母会整个块发生变化的情况，也说明应该存在循环的处理，所以如果找到循环的处理，说明这个位置很可疑</li>
<li>修改：如果对原位置进行了修改，就很可能是加密过程（不过最后在这个程序中没有出现在原位置上修改）</li>
<li>输出数据：如果看到输出数据出现了，那么即使没有找到程序位置，也可以通过下 watchpoint 查看对输出数据位置进行修改，就可以找到程序的关键位置了</li>
</ol>
<p>这个的中间过程比较长，细节也很多，我也没有办法把每一个动作都记下来，总的来说，通过不断的调试跟踪，我找到了输出数据的位置，位于 <code>0x55555579dc80</code> （关闭 ASLR），然后通过 watchpoint 找到了程序的加密函数位置，位于 <code>0x97f0</code> ，其中有两个循环。</p>
<p>其中有一个逆向 Rust 程序的经验，Rust 的程序的参数如果是 <code>Result&lt;T, E&gt;</code> 这种，或者 <code>Option&lt;T&gt;</code> 这种，一般来说第一个参数是输出，也就是需要返回的 <code>Result</code> 或者 <code>Option</code> ，为了取出其中的数据，就会有很多额外的函数，这些函数没有太大的逆向意义，里边会有比较深的调用，但是仔细看会发现最终基本都会是一个函数直接返回其参数值或是返回其参数值位置的数据（类似于 <code>return *a1</code> 这样的），这些函数就可以直接认为是取出内容值就行了，不需要仔细去逆向，这样可以避免迷失在大量的函数当中。</p>
<p>找到关键函数之后就不难了，通过在循环里下断点观察循环的执行过程，然后就可以定位到两个关键函数，一个是位于 <code>0x9b4b</code> 的函数调用，其参数是取出的一个 key 和上一位的数据，另一个是位于 <code>0x9b64</code> 的函数调用，是一个异或操作。</p>
<p>所以整个算法如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">input: key[], chunk[](在初始状态下，chunk 中存储了 flag 的内容，后面的内容都为 \x00)</span><br><span class="line"></span><br><span class="line">def op1(x, y):</span><br><span class="line">    val = 0</span><br><span class="line">    while i &gt; 0:</span><br><span class="line">        if x &amp; 1 &gt; 0:</span><br><span class="line">            val ^= x</span><br><span class="line">        x *= 2</span><br><span class="line">        if x &gt;= 0x100:</span><br><span class="line">            x ^= 0x11d</span><br><span class="line">    return val</span><br><span class="line"></span><br><span class="line">def cipher(key, chunk(0x10 为一个chunk)):</span><br><span class="line">    for i in range(0x10):</span><br><span class="line">        for j in range(0x20):</span><br><span class="line">            chunk[i + j] = op1(key[j], chunk[i])</span><br><span class="line">            chunk[i + j] ^= chunk[i + j + 1]</span><br><span class="line"></span><br><span class="line">    return chunk[0x10:] (大小为0x20)</span><br></pre></td></tr></table></figure>
<p>根据这个算法，首先 op1 函数类似于指数操作，所以可以通过爆破方式求”对数“，异或操作的一个 bug 在于每一个都需要额外的一个 byte ，而这个额外的 byte 始终是 0 ，所以相当于最后一个 byte 是可以恢复的，通过最后一个 byte 就可以恢复出 chunk[i] ，从而恢复出每一轮。</p>
<h3 id="求解脚本">求解脚本</h3>
<p>Ocaml 写的，运行需要 <code>core</code> 和 <code>utop</code> （utop 主要是用来当脚本运行，如果没有也可以编译运行），运行方式：<code>utop -require core solve.ml</code></p>
<figure class="highlight ocaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">open</span> <span class="type">Core</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> key = [|</span><br><span class="line">  <span class="number">0x74</span>; <span class="number">0x40</span>; <span class="number">0x34</span>;</span><br><span class="line">  <span class="number">0xae</span>; <span class="number">0x36</span>; <span class="number">0x7e</span>; <span class="number">0x10</span>;</span><br><span class="line">  <span class="number">0xc2</span>; <span class="number">0xa2</span>; <span class="number">0x21</span>; <span class="number">0x21</span>;</span><br><span class="line">  <span class="number">0x9d</span>; <span class="number">0xb0</span>; <span class="number">0xc5</span>; <span class="number">0xe1</span>;</span><br><span class="line">  <span class="number">0x0c</span>; <span class="number">0x3b</span>; <span class="number">0x37</span>; <span class="number">0xfd</span>;</span><br><span class="line">  <span class="number">0xe4</span>; <span class="number">0x94</span>; <span class="number">0x2f</span>; <span class="number">0xb3</span>;</span><br><span class="line">  <span class="number">0xb9</span>; <span class="number">0x18</span>; <span class="number">0x8a</span>; <span class="number">0xfd</span>;</span><br><span class="line">  <span class="number">0x14</span>; <span class="number">0x8e</span>; <span class="number">0x37</span>; <span class="number">0xac</span>;</span><br><span class="line">  <span class="number">0x58</span>;</span><br><span class="line">|]</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> op1 x y =</span><br><span class="line">  <span class="keyword">let</span> init_val = <span class="built_in">ref</span> <span class="number">0</span> <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> x = <span class="built_in">ref</span> x <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> y = <span class="built_in">ref</span> y <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">while</span> !y &gt; <span class="number">0</span> <span class="keyword">do</span></span><br><span class="line">    <span class="keyword">if</span> !y <span class="keyword">land</span> <span class="number">1</span> = <span class="number">1</span> <span class="keyword">then</span> <span class="keyword">begin</span></span><br><span class="line">      init_val := !init_val <span class="keyword">lxor</span> !x;</span><br><span class="line">    <span class="keyword">end</span>;</span><br><span class="line">    x := !x * <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">if</span> !x &gt;= <span class="number">0x100</span> <span class="keyword">then</span> <span class="keyword">begin</span></span><br><span class="line">      x := !x <span class="keyword">lxor</span> <span class="number">0x11d</span>;</span><br><span class="line">    <span class="keyword">end</span>;</span><br><span class="line">    y := !y <span class="keyword">lsr</span> <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">done</span>;</span><br><span class="line">  !init_val</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> op1_rev res x =</span><br><span class="line">  <span class="keyword">let</span> y = <span class="built_in">ref</span> <span class="number">0</span> <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">try</span></span><br><span class="line">    <span class="keyword">for</span> i = <span class="number">0</span> <span class="keyword">to</span> <span class="number">0xff</span> <span class="keyword">do</span></span><br><span class="line">      y := i;</span><br><span class="line">      <span class="keyword">if</span> op1 x !y = res <span class="keyword">then</span> <span class="keyword">begin</span></span><br><span class="line">        raise <span class="type">Exit</span></span><br><span class="line">      <span class="keyword">end</span></span><br><span class="line">    <span class="keyword">done</span>;</span><br><span class="line">    raise (<span class="type">Failure</span> <span class="string">"not found"</span>)</span><br><span class="line">  <span class="keyword">with</span></span><br><span class="line">    | <span class="type">Exit</span> -&gt; !y</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> chunk_rev chunk =</span><br><span class="line">  <span class="keyword">let</span> chunk = <span class="built_in">ref</span> chunk <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> current_byte = <span class="built_in">ref</span> <span class="number">0</span> <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> chunk_len = <span class="type">Array</span>.length !chunk <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> key_len = <span class="type">Array</span>.length key <span class="keyword">in</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> i = chunk_len - <span class="number">1</span> <span class="keyword">downto</span> <span class="number">0</span> <span class="keyword">do</span></span><br><span class="line">    <span class="keyword">let</span> final_key = <span class="number">0x58</span> <span class="keyword">in</span></span><br><span class="line">    current_byte := op1_rev !chunk.(chunk_len - <span class="number">1</span>) final_key;</span><br><span class="line">    <span class="comment">(*Printf.printf "current byte 0x%x\n" !current_byte;*)</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> j = key_len - <span class="number">1</span> <span class="keyword">downto</span> <span class="number">0</span> <span class="keyword">do</span></span><br><span class="line">      !chunk.(j) &lt;- (op1 key.(j) !current_byte) <span class="keyword">lxor</span> !chunk.(j);</span><br><span class="line">    <span class="keyword">done</span>;</span><br><span class="line"></span><br><span class="line">    chunk := <span class="type">Array</span>.append [|!current_byte|] !chunk;</span><br><span class="line"></span><br><span class="line">    <span class="comment">(*</span></span><br><span class="line"><span class="comment">    for j = 0 to chunk_len do</span></span><br><span class="line"><span class="comment">      Printf.printf "0x%x " !chunk.(j);</span></span><br><span class="line"><span class="comment">    done;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    Printf.printf "\n";*)</span></span><br><span class="line">  <span class="keyword">done</span>;</span><br><span class="line">  !chunk</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> decode fmt =</span><br><span class="line">  <span class="type">String</span>.split ~on:<span class="string">' '</span> fmt |&gt;</span><br><span class="line">  <span class="type">List</span>.map ~f:(<span class="keyword">fun</span> x -&gt; <span class="type">Int</span>.of_string (<span class="string">"0x"</span> ^ x)) |&gt;</span><br><span class="line">  <span class="type">List</span>.to_array</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> hex x = <span class="type">Printf</span>.sprintf <span class="string">"0x%x"</span> x</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> print_result arr =</span><br><span class="line">  <span class="type">Array</span>.filter ~f:((&lt;&gt;) <span class="number">0</span>) arr |&gt;</span><br><span class="line">  <span class="type">Array</span>.iter ~f:(<span class="keyword">fun</span> x -&gt; <span class="type">Printf</span>.printf <span class="string">"%c"</span> (<span class="type">Char</span>.of_int_exn x))</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> print_arr arr =</span><br><span class="line">  <span class="type">Array</span>.iter ~f:(<span class="keyword">fun</span> x -&gt; <span class="type">Printf</span>.printf <span class="string">"0x%x "</span> x) arr</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> split_arr arr = <span class="type">Array</span>.partitioni_tf arr ~f:(<span class="keyword">fun</span> i x -&gt;</span><br><span class="line">  <span class="keyword">if</span> i &lt; <span class="number">32</span> <span class="keyword">then</span> <span class="literal">true</span> <span class="keyword">else</span> <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> solve s =</span><br><span class="line">  <span class="keyword">let</span> a = decode s <span class="keyword">in</span></span><br><span class="line">  <span class="keyword">let</span> <span class="keyword">rec</span> solve_part chunk rest =</span><br><span class="line">    <span class="keyword">if</span> <span class="type">Array</span>.length chunk &gt; <span class="number">0</span> <span class="keyword">then</span></span><br><span class="line">      chunk_rev chunk |&gt; print_result;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> <span class="type">Array</span>.length rest &gt; <span class="number">0</span> <span class="keyword">then</span></span><br><span class="line">        <span class="keyword">let</span> chunk, rest = split_arr rest <span class="keyword">in</span></span><br><span class="line">        solve_part chunk rest;</span><br><span class="line">  <span class="keyword">in</span></span><br><span class="line">  solve_part <span class="literal">[||]</span> a</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> cipher = <span class="string">"ef 43 4b 3f 5e b9 f0 d0 8c b5 7e 6f 7b c8 a6 7b 09 e2 61 9d 98 03 5f 56 5d 66 82 0b 9e 2b 76 92 5b c3 dc f2 3c d0 b6 81 60 34 a5 66 ca bd 7d 6a 00 fe e4 0b 44 e1 ba 81 cb ae 8b 24 0b a5 1f 6d ba 0e 61 1a 30 a7 77 51 23 41 a6 1a c0 7f 71 71 9f d5 93 e5 38 ce 52 8b 25 86 b3 12 b7 a7 1c 43 b4 08 81 47 ae d6 18 46 c5 6b 69 63 0b cc 95 ab 49 53 6f de be 2f 2e d9 9b dc dd 76 69 a4 f0 58"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="literal">()</span> = solve cipher</span><br></pre></td></tr></table></figure>

    </div>
    
    <div class="post-footer">
        <div>
            
            转载声明：
            商业转载请联系作者获得授权,非商业转载请注明出处 © <a href="" target="_blank">Snippet</a>
            
            
        </div>
        <div>
            
        </div>
    </div>
</article>
<div class="article-nav prev-next-wrap clearfix">
    
    <a href="/2020/02/10/for-non-prof-basic-1/" class="pre-post btn btn-default" title='非专业计算机基础 (1)'>
        <i class="fa fa-angle-left fa-fw"></i><span class="hidden-lg">上一篇</span>
        <span class="hidden-xs">
            非专业计算机基础 (1)</span>
    </a>
    
    
    <a href="/2020/02/09/codegate-2020/" class="next-post btn btn-default" title='codegate-2020-1'>
        <span class="hidden-lg">下一篇</span>
        <span class="hidden-xs">
            codegate-2020-1</span><i class="fa fa-angle-right fa-fw"></i>
    </a>
    
</div>

<div id="comments">
    

<div id="vcomments" class="valine"></div>
<!--<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="/assets/valine.min.js"></script>-->
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="//unpkg.com/valine@latest/dist/Valine.min.js"></script>
<script>
new Valine({
    av: AV,
    el: '#vcomments',
    appId: 'sBJ8fsglfz3e3AeXQbE8d8H8-gzGzoHsz',
    appKey: 'WFXH17M73py6bGqWl0ffMbHG',
    placeholder: '说点什么吧',
    notify: false,
    verify: true,
    avatar: 'mm',
    meta: 'nick,mail'.split(','),
    pageSize: '10',
    path: window.location.pathname,
    lang: 'zh-CN'.toLowerCase()
})
</script>



</div>


                </main>
                
                    <aside id="article-toc" role="navigation" class="col-md-4">
    <div class="widget">
        <h3 class="title">
            文章目录
        </h3>
        
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#codegate-两道简单题-2"><span class="toc-text">CodeGate 两道简单题 (2)</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#reverse-rs"><span class="toc-text">reverse: RS</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#题目信息"><span class="toc-text">题目信息</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#找到关键函数"><span class="toc-text">找到关键函数</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#求解脚本"><span class="toc-text">求解脚本</span></a></li></ol></li></ol></li></ol>
        
    </div>
</aside>
                
            </div>
        </div>
    </section>
    <footer class="main-footer">
    <div class="container">
        <div class="row">
        </div>
    </div>
</footer>
<a id="back-to-top" class="icon-btn hide">
    <i class="fa fa-chevron-up"></i>
</a>
    <div class="copyright">
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                <div class="busuanzi">
    
    访问量:
    <strong id="busuanzi_value_site_pv">
        <i class="fa fa-spinner fa-spin"></i>
    </strong>
    &nbsp; | &nbsp;
    访客数:
    <strong id="busuanzi_value_site_uv">
        <i class="fa fa-spinner fa-spin"></i>
    </strong>
    
</div>
            </div>
            <div class="col-sm-12">
                <span>Copyright &copy;
                    2019
                </span> |
                <span>
                    Powered by <a href="//hexo.io" class="copyright-links" target="_blank" rel="nofollow">Hexo</a>
                </span> |
                <span>
                    Theme by <a href="//github.com/shenliyang/hexo-theme-snippet.git" class="copyright-links" target="_blank" rel="nofollow">Snippet</a>
                </span>
            </div>
        </div>
    </div>
</div>


<script src="/assets/tagcanvas.min.js?rev=2.9"></script>
<script>
var tagOption = {
    textColour: '#444', // 字体颜色
    outlineMethod: 'block', // 选中模式
    outlineColour: '#FFDAB9', // 选中模式的颜色
    interval: 30 || 30, // 动画帧之间的时间间隔，值越大，转动幅度越大
    textHeight: 13,
    outlineRadius: 3,
    freezeActive: true || '', // 选中的标签是否继续滚动
    frontSelect: true || '', // 不选标签云后部的标签
    initial: [0.1, -0.1],
    depth: 0.5,
    decel: 0.95,
    maxSpeed: 0.03,
    reverse: true || '', // 是否反向触发
    fadeIn: 500, // 进入动画时间
    wheelZoom: false || '' // 是否启用鼠标滚轮
}
TagCanvas.Start('tag-cloud-3d', '', tagOption);
</script>


<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

<script src="/js/app.js?rev=@@hash"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->
</body>
</html>